<?php

/**
 * This is the model class for table "news".
 *
 * The followings are the available columns in table 'news':
 * @property integer $_id
 * @property integer $insertTime
 * @property integer $updateTime
 * @property integer $dateTime
 * @property boolean $notified
 * @property boolean $sticky
 * @property boolean $hidden
 * @property string $type
 * @property string $sender
 * @property string $contact
 * @property string $host
 * @property string $value
 */
class News extends ActiveRecord {

	const TYPE_SMS = 'sms';
	const TYPE_WEB = 'web';
	const TYPE_TWITTER = 'twitter';
	const TYPE_EMAIL = 'email';
	const TYPE_NTMC = 'ntmc';

	/**
	 * @property date date for download scenario.
	 */
	public $date;

	/**
	 * Returns the static model of the specified AR class.
	 * @return News the static model class
	 */
	public static function model($className = __CLASS__) {
		return parent::model($className);
	}

	/**
	 * @return string the associated database table name
	 */
	public function tableName() {
		return 'news';
	}

	/**
	 * @return array validation rules for model attributes.
	 */
	public function rules() {
		// NOTE: you should only define rules for those attributes that
		// will receive user inputs.
		return array(
			array('value', 'required', 'on'=>'insert, update'),
			array('dateTime, sticky, hidden', 'numerical', 'integerOnly'=>true),
			array('sender, contact', 'length', 'max'=>255),
			array('date', 'required', 'on'=>'download'),
			array('date', 'date', 'on'=>'download', 'format'=>'yyyy-MM-dd'),
			// The following rule is used by search().
			// Please remove those attributes that should not be searched.
			array('sender, sticky, hidden', 'safe', 'on'=>'search'),
		);
	}

	/**
	 * @return array relational rules.
	 */
	public function relations() {
		// NOTE: you may need to adjust the relation name and the related
		// class name for the relations automatically generated below.
		return array(
		);
	}

	/**
	 * @return array customized attribute labels (name=>label)
	 */
	public function attributeLabels() {
		return array(
			'dateTime'=>'Waktu',
			'notified'=>'Notified',
			'sticky'=>'Atensi',
			'hidden'=>'Hidden',
			'type'=>'Type',
			'sender'=>'Callsign',
			'senderMinimal'=>'Pengirim',
			'contact'=>'Telp / HP',
			'value'=>'Pesan (tanpa sandi di radio)',
		);
	}

	/**
	 * Retrieves a list of models based on the current search/filter conditions.
	 * @return CActiveDataProvider the data provider that can return the models
	 * based on the search/filter conditions.
	 */
	public function search() {
		// Warning: Please modify the following code to remove attributes that
		// should not be searched.

		$criteria = new CDbCriteria;

		$criteria->compare('sticky', $this->sticky);
		$criteria->compare('hidden', $this->hidden);
		$criteria->compare('sender', $this->sender, true);

		$config = array(
			'criteria'=>$criteria,
		);
		return new CActiveDataProvider(get_class($this), $config);
	}

	/**
	 * We're overriding this method to fill findAll() and similar method result
	 * with proper models.
	 *
	 * @param array $attributes
	 * @return News
	 */
	protected function instantiate($attributes) {
		switch ($attributes['type']) {
			case self::TYPE_SMS:
				$class = 'SmsNews';
				break;
			case self::TYPE_WEB:
				$class = 'WebNews';
				break;
			case self::TYPE_TWITTER:
				$class = 'TwitterNews';
				break;
			case self::TYPE_NTMC:
				$class = 'NtmcNews';
				break;
			case self::TYPE_EMAIL:
				$class = 'EmailNews';
				break;
			default:
				$class = get_class($this);
		}
		$model = new $class(null);
		return $model;
	}

	/**
	 * If new record, set notified, sticky and hidden to false.
	 * If sender is blacklisted, set hidden and notified to true;
	 *
	 * @see CActiveRecord beforeSave.
	 */
	protected function beforeSave() {
		if (!parent::beforeSave()) return false;
		$this->value = preg_replace('/[\x80-\xFF]/', '', $this->value);
		if ($this->isNewRecord) {
			$this->notified = 0;
			$this->sticky = 0;
			$this->hidden = 0;
			$this->checkSender();
			$this->checkKeyword();
			$this->censor();
		}
		return true;
	}

	/**
	 * Check whether sender is blacklisted.
	 */
	protected function checkSender() {
		$condition = 'value=:value and type=:type';
		$params = array(':value'=>$this->contact, ':type'=>$this->type);
		if (Blacklist::model()->exists($condition, $params)) {
			$this->hidden = 1;
			$this->notified = 1;
		}
	}

	/**
	 * Check whether content contains blacklisted word.
	 */
	protected function checkKeyword() {
		if ($this->hidden) return;

		$criteria = new CDbCriteria;
		$condition = '`type` == :type';
		$criteria->condition = $condition;
		$criteria->params[':type'] = Blacklist::TYPE_KEYWORD;
		$models = Blacklist::model()->findAll($criteria);
		$found = false;
		$search = array(' ', '/');
		$replace = array('|', '\/');
		foreach ($models as $model) {
			$keyword = str_replace($search, $replace, $model->value);
			$pattern = '/\b(' . $keyword . ')\b/i';
			$found = preg_match($pattern, $this->value);
			if ($found) break;
			else {
				$found = preg_match($pattern, $this->sender);
				if ($found) break;
				else {
					$found = preg_match($pattern, $this->contact);
					if ($found) break;
				}
			}
		}
		if ($found) {
			$this->hidden = 1;
			$this->notified = 1;
		}
	}

	protected function censor() {
		if (!$this->isNewRecord) return;

		$models = Censor::model()->findAll();
		$subject = $this->value;
		foreach ($models as $model) {
			$pattern = "/\b{$model->search}\b/i";
			$replacement = $model->replace;
			$subject = preg_replace($pattern, $replacement, $subject);
		}
		$this->value = $subject;
	}

	/**
	 * @property-read string sender name in complete form
	 * [name [- contact @ host]]
	 */
	public function getSenderComplete() {
		if ($this->type == self::TYPE_SMS) return $this->contact;

		$sender = $this->sender;
		if ($this->type == self::TYPE_TWITTER ||
			$this->type == self::TYPE_NTMC) return $sender;

		if ($this->contact) $sender .= ' - ' . $this->contact;
		//$sender .= ' @ ' . $this->host;
		return $sender;
	}

	/**
	 * @property-read string sender name in minimal form
	 */
	public function getSenderMinimal() {
		if ($this->type == self::TYPE_SMS) return $this->contact;
		return $this->sender;
	}

	/**
	 * Hide news.
	 * @return boolean whether the hiding succeeds
	 */
	public function hide() {
		$this->hidden = 1;
		return $this->save();
	}

	/**
	 * Unhide news.
	 * @return boolean whether the unhiding succeeds
	 */
	public function unhide() {
		$this->hidden = 0;
		return $this->save();
	}

	/**
	 * Sticky news.
	 * @return boolean whether the sticking succeeds
	 */
	public function sticky() {
		$this->sticky = 1;
		return $this->save();
	}

	/**
	 * Unsticky news.
	 * @return boolean whether the unsticking succeeds
	 */
	public function unsticky() {
		$this->sticky = 0;
		return $this->save();
	}

	/**
	 * Blacklist sender.
	 *
	 * @return boolean whether the blacklist succeeds
	 */
	public function blacklist() {
		$this->hidden = 1;
		$this->notified = 1;
		$this->save();

		$condition = 'value=:value and type=:type';
		$params = array(':value'=>$this->contact, ':type'=>$this->type);
		if (Blacklist::model()->exists($condition, $params)) return true;

		$blacklist = new Blacklist;
		$blacklist->value = $this->contact;
		$blacklist->type = $this->type;
		return $blacklist->save();
	}

	protected $_blacklisted = null;

	public function getBlacklisted() {
		if ($this->_blacklisted === null) {
			$condition = 'value=:value and type=:type';
			$params = array(':value'=>$this->sender, ':type'=>$this->type);
			$blacklist = Blacklist::model();
			$this->_blacklisted = $blacklist->exists($condition, $params);
		}
		return $this->_blacklisted;
	}

	/**
	 * Send mail notification.
	 *
	 * @return boolean whether notification sent
	 */
	public function sendNotification() {
		if ($this->notified) return true;

		$subject = "News from Senkom Information Center";
		$date = $this->dateTime;
		$formatter = Yii::app()->dateFormatter;
		$date = $formatter->formatDateTime($date, null, 'short');
		$body = "SIC-ID: #$this->_id\r\n\r\n";
		$body .= "$this->senderComplete ($date)\r\n$this->value";
		$notification = new NotificationMailMessage($subject, $body);
		if (Yii::app()->mail->send($notification)) {
			$this->notified = 1;
			$this->save(false);
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Send mail news hiding notification.
	 *
	 * @return boolean whether news hidden successfuly
	 */
	public function sendHideNotification() {
		$subject = "Hide news success";
		$date = $this->dateTime;
		$formatter = Yii::app()->dateFormatter;
		$date = $formatter->formatDateTime($date, null, 'short');
		$body = "SIC-ID: #$this->_id berhasih disensor (hide).\r\n\r\n";
		$body .= "$this->senderComplete ($date)\r\n$this->value";
		$notification = new NotificationMailMessage($subject, $body);
		return Yii::app()->mail->send($notification);
	}

	/**
	 * Send mail news blaclisting notification.
	 *
	 * @return boolean whether news blacklisted successfuly
	 */
	public function sendBlacklistNotification() {
		$subject = "Blacklist news success";
		$date = $this->dateTime;
		$formatter = Yii::app()->dateFormatter;
		$date = $formatter->formatDateTime($date, null, 'short');
		$body = "SIC-ID: #$this->_id berhasih di-blok (blacklist).\r\n\r\n";
		$body .= "$this->senderComplete ($date)\r\n$this->value";
		$notification = new NotificationMailMessage($subject, $body);
		return Yii::app()->mail->send($notification);
	}

}